from os import abort

from django.http import HttpResponse
from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework.views import APIView
from QQLoginTool.QQtool import OAuthQQ
from rest_framework.response import Response
from django.conf import settings
from rest_framework import status
from rest_framework_jwt.settings import api_settings

from meiduo_mall.utils.captcha.captcha import captcha
from .models import OAuthQQUser, OAuthSinaUser
from .utils import generate_save_user_token, OAuthWeibo, generate_user_token
from .serializers import QQAuthUserSerializer, WeiboOauthSerializer
import logging

logger = logging.getLogger('django')
from carts.utils import merge_cart_cookie_to_redis


# Create your views here.
class QQOauthURLView(APIView):
    """拼接好QQ登录网址"""

    def get(self, request):
        # 1.提取前端传入的next参数记录用户从那里去login界面
        # next = request.query_params.get('next') or '/'
        # get(self,key,default=None):获取指定key的值,如果获取的key不存在,可以返回default参数的值
        next = request.query_params.get('next', '/')

        # QQ登录参数
        # QQ_CLIENT_ID = '101514053'
        # QQ_CLIENT_SECRET = '1075e75648566262ea35afa688073012'
        # QQ_REDIRECT_URI = 'http://www.meiduo.site:8080/oauth_callback.html'

        # 2.利用QQ登录数据
        # oauth = OAuthQQ(client_id=appid, client_secret=appkey, redirect_uri=回调域名, state=记录来源)
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI, state=next)
        # 创建QQ登录工具对象
        login_url = oauth.get_qq_url()
        # 调用它里面的方法,拼接好QQ登录网址
        return Response({'login_url': login_url})


class QQAuthUserView(APIView):
    """QQ登录成功后的回调处理"""

    def get(self, request):
        # 1.获取前端传入的code

        code = request.query_params.get('code')
        if not code:  # 如果没有获取到code
            return Response({'message': '缺少code'}, status=status.HTTP_400_BAD_REQUEST)
        # 2.创建QQ登录工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        try:

            # 3.调用它里面的get_access_token(code) 用code向qq服务器获取access_token
            access_token = oauth.get_access_token(code)
            # 4.调用它里面的get_open_id(assess_token) 用access_token响应QQ服务器获取openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.info(e)
            return Response({'message': 'QQ服务器异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 5.查询数据库有没有这个openid
        try:
            authQQUserModel = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 6.如果openid没有绑定用户 应该创建用户并绑定openid,让前端先保存一会儿,等需要时在使用
            access_token_openid = generate_save_user_token(openid)
            return Response({'access_token': access_token_openid})
        else:
            # 7.如果openid已绑定美多用户 那么直接代表登录成功,给前端返回JWT状态保持信息

            user = authQQUserModel.user  # 获取到openid 关联的user

            from rest_framework_jwt.settings import api_settings

            # 补充生成记录登录状态的token
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 引用jwt中的叫jwt_payload_handler函数(生成payload)
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 函数引用 生成jwt

            payload = jwt_payload_handler(user)  # 根据user生成用户相关的载荷
            token = jwt_encode_handler(payload)  # 传入载荷生成完整的jwt

            response = Response({
                'token': token,
                'username': user.username,
                'user_id': user.id

            })

            # 在此调用合并购物车函数
            merge_cart_cookie_to_redis(request, user, response)

            return response
        # 如果没有这个openid 应该创建一个新用户和此openid绑定
        # 如果数据库中有此openid 直接代表登录成功,给前端返回JWT 状态保持信息

    def post(self, request):
        """openid绑定用户接口"""
        # 创建序列化器进行反序列化
        serializer = QQAuthUserSerializer(data=request.data)
        # 调用is_valid方法进行校验
        serializer.is_valid(raise_exception=True)
        # 调用序列化器的save方法
        user = serializer.save()

        # 补充生成记录登录状态的token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 引用jwt中的叫jwt_payload_handler函数(生成payload)
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 函数引用 生成jwt

        payload = jwt_payload_handler(user)  # 根据user生成用户相关的载荷
        token = jwt_encode_handler(payload)  # 传入载荷生成完整的jwt

        response = Response({
            'token': token,
            'username': user.username,
            'user_id': user.id

        })

        # 在此调用合并购物车函数
        merge_cart_cookie_to_redis(request, user, response)
        # 响应
        return response


class WeiboAuthURLLView(APIView):
    """定义微博第三方登录的视图类"""

    def get(self, request):
        """
        获取微博登录的链接
        oauth/weibo/authorization/?next=/
        :param request:
        :return:
        """
        next = request.query_params.get('next', '/')
        oauth = OAuthWeibo(client_id=settings.WEIBO_CLIENT_ID,
                           client_secret=settings.WEIBO_CLIENT_SECRET,
                           redirect_uri=settings.WEIBO_REDIRECT_URI,
                           state=next)
        login_url = oauth.get_weibo_url()

        return Response({"login_url": login_url})


class WeiboOauthView(APIView):
    """微博登录成功后的回调处理"""

    def get(self, request):
        # 1.获取code值
        code = request.query_params.get("code")

        if not code:  # 如果没有获取到code
            return Response({'message': '缺少code'}, status=status.HTTP_400_BAD_REQUEST)
        # 2.创建微博登录工具对象
        oauth = OAuthWeibo(client_id=settings.WEIBO_CLIENT_ID,
                           client_secret=settings.WEIBO_CLIENT_SECRET,
                           redirect_uri=settings.WEIBO_REDIRECT_URI,
                           state=next)

        try:

            access_token = oauth.get_access_token(code=code)
            print(access_token)

        except Exception as e:

            logger.info(e)

            return Response({'message': '微博服务器异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        try:
            weibo_user = OAuthSinaUser.objects.get(access_token=access_token)

        except OAuthSinaUser.DoesNotExist:
            access_token_id = generate_user_token(access_token)
            return Response({'access_token': access_token_id})

        else:
            # 7.绑定过,则登录成功
            # 生成jwt-token值
            user = weibo_user.user
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            payload = jwt_payload_handler(user)  # 生成载荷部分
            token = jwt_encode_handler(payload)  # 生成token

            response = Response(
                {
                    'token': token,
                    'username': user.username,
                    'user_id': user.id
                }
            )

        return response

    def post(self, request):
        # 1. 获取前端数据
        data = request.data
        # 2.调用序列化器验证数据
        serializer = WeiboOauthSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)  # 生成载荷部分
        token = jwt_encode_handler(payload)  # 生成token

        return Response(
            {
                'token': token,
                'username': user.username,
                'user_id': user.id
            }
        )


class GetImageCodeView(APIView):
    """获取图片验证码"""

    def get(self, request, image_code_id):

        # 调用工具类生成验证码图片，验证码真实值
        name, text, image = captcha.generate_captcha()

        # 创建redis连接对象
        redis_conn = get_redis_connection('verify_codes')

        try:
            redis_conn.setex("Image_Code_%s" % image_code_id, 300, text.lower())

        except:

            return Response({'message': '图片验证码存储错误'})
        print(text)

        return HttpResponse(image, content_type='image/png')
